package com.tannm.doan.taskmanager.dataview;

import java.util.*;

import com.tannm.doan.taskmanager.Prefs;
import com.tannm.doan.taskmanager.RepeatData;
import com.tannm.doan.taskmanager.RepeatDataValue;
import com.tannm.doan.taskmanager.Utils;
import com.tannm.doan.taskmanager.agenda.AgendaView;
import com.tannm.doan.taskmanager.database.DataRowAppointment;
import com.tannm.doan.taskmanager.database.Database;

import android.database.Cursor;

public class DataViewAppointment extends DataView {
	// fields
	private Calendar calUtilDate = Calendar.getInstance();

	// fields
	private RepeatData repeat = new RepeatData();

	// fields
	protected Calendar calStartDateForCache = Calendar.getInstance();
	protected RepeatDataValue[] vecDateRangeCache = new RepeatDataValue[42];

	// fields
	private Calendar date1cmp = Calendar.getInstance();
	private Calendar date2cmp = Calendar.getInstance();

	// fields
	private Calendar calItemStartDate = Calendar.getInstance();

	// Comparator type
	public class RowsComparator implements Comparator<DataViewItem> {
		public int compare(DataViewItem item1, DataViewItem item2) {
			date1cmp.setTimeInMillis(item1.getStartDateAsLong());
			date2cmp.setTimeInMillis(item2.getStartDateAsLong());

			boolean bAllDay1 = (item1.bAllDay);
			boolean bAllDay2 = (item2.bAllDay);

			if (bAllDay1 && bAllDay2) {
				String s1 = item1.sSubject;
				String s2 = item2.sSubject;
				return s1.compareTo(s2);
			} else {
				if (bAllDay1)
					return -1;
				if (bAllDay2)
					return 1;

				if (Utils.getTimeAsSeconds(date1cmp) > Utils
						.getTimeAsSeconds(date2cmp))
					return 1;
				if (Utils.getTimeAsSeconds(date1cmp) < Utils
						.getTimeAsSeconds(date2cmp))
					return -1;

				if (Utils.getTimeAsSeconds(date1cmp) == Utils
						.getTimeAsSeconds(date2cmp)) {
					String s1 = item1.sSubject;
					String s2 = item2.sSubject;
					return s1.compareTo(s2);
				}
			}
			return 0;
		}
	};

	// fields
	private RowsComparator fnCmp = null;

	// methods
	public DataViewAppointment(Database db, Prefs prefs) {
		super(db, prefs);
		sTableName = Database.sTableNameAppointments;
		fnCmp = new RowsComparator();

		// initialize date value cache
		for (int iDay = 0; iDay < 42; iDay++) {
			vecDateRangeCache[iDay] = new RepeatDataValue();
		}
	}

	@Override
	public void addItem(Cursor cr) {
		DataViewItem item = new DataViewItem();

		item.lID = cr.getLong(DataRowAppointment.Fid.ID);
		item.sSubject = cr.getString(DataRowAppointment.Fid.SUBJECT);
		item.setStartDate(calUtilDate, cr
				.getLong(DataRowAppointment.Fid.START_DATE));
		item.iDurationInMinutes = cr
				.getInt(DataRowAppointment.Fid.DURATION_IN_MINUTES);
		item.bAllDay = (cr.getLong(DataRowAppointment.Fid.ALL_DAY) == 1);
		item.bAlarm = (cr.getLong(DataRowAppointment.Fid.ALARM) == 1);

		item.iRepeatType = cr.getInt(DataRowAppointment.Fid.REPEAT_TYPE);

		if (!cr.isNull(DataRowAppointment.Fid.REPEAT_EVERY))
			item.iRepeatEvery = cr.getInt(DataRowAppointment.Fid.REPEAT_EVERY);

		if (!cr.isNull(DataRowAppointment.Fid.REPEAT_END_ON_DATE))
			item.lRepeatEndOnDate = cr
					.getLong(DataRowAppointment.Fid.REPEAT_END_ON_DATE);

		rows.add(item);
	}

	@Override
	public void filterDataForView(DataViewItem item,
			final Calendar calStartDate, final int agendaViewType) {
		// set repeat comparer data
		repeat.setRepeatTypeAsInt(item.iRepeatType);
		repeat.setEndOnDate(null);
		repeat.setEvery(1);

		// if repeat set
		if (item.isRepeat()) {
			repeat.setEvery(item.iRepeatEvery);
			if (item.useRepeatEndOnDate())
				repeat.setEndOnDate(item.lRepeatEndOnDate);
		}

		// get appt item start date
		calItemStartDate.setTimeInMillis(item.getStartDateAsLong());
		calItemStartDate.setFirstDayOfWeek(prefs.iFirstDayOfWeek);
		repeat.setStartDate(calItemStartDate);

		// filter item for date range
		if (agendaViewType != AgendaView.viewMode.NONE) {
			item.clear();

			final int iDaysCount = getDaysRangeForView(agendaViewType);

			if (iDaysCount == 0) {

				if (repeat.isDateEqual(calStartDate)) {
					item.setVisibleDay(0);
					item.viewMode = agendaViewType;
				}

			} else {

				RepeatDataValue dvDate = null;

				for (int iDay = 0; iDay < iDaysCount; iDay++) {
					dvDate = vecDateRangeCache[iDay];

					if (repeat.isDateEqual(dvDate)) {
						item.setVisibleDay(iDay);
						item.viewMode = agendaViewType;
					}

				}

			}
		}

	}

	@Override
	protected void filterDataPrepare(final Calendar calStartDate,
			final int agendaViewType) {
		final int iDaysCount = getDaysRangeForView(agendaViewType);

		int iDayValue = 1;
		// cache date values backward for alarm service
		if (agendaViewType == AgendaView.viewMode.TODAY_ALARM)
			iDayValue = -1;

		calStartDateForCache.setTimeInMillis(calStartDate.getTimeInMillis());
		calStartDateForCache.setFirstDayOfWeek(prefs.iFirstDayOfWeek);

		for (int iDay = 0; iDay < (iDaysCount); iDay++) {
			vecDateRangeCache[iDay].getFromCalendar(calStartDateForCache);
			calStartDateForCache.add(Calendar.DAY_OF_YEAR, iDayValue);
		}

	}

	@Override
	public void sortView() {
		Collections.sort(rows, fnCmp);
	}

}
